#pragma once
#ifndef _ZELESTE_ZEL_UTILS_VIRTUALFILESYSTEM_H_
#define _ZELESTE_ZEL_UTILS_VIRTUALFILESYSTEM_H_

#include <boost/filesystem.hpp>
#include "../../core/datatypes/cuManager.h"

namespace lpe{
	namespace resman{
		/*! \brief This class represents a virtual file system. With this class you gain the ability to put your files in a 7z file.
		*
		* The CVirtualFileSystem class is a wrapper for icculus physfs system. You can use this class to extract (deploy) your files from a compressed
		* file. The class use a manager in order to keep track of the deployed files. 
		* The CVirtualFileSystem first needs a base path. Inside this directory, all resources and directories must be set.
		* A simple example:
		* <b>[Init VFS]</b>
		* <code>
		* lpe::utils::CVirtualFileSystem vfs;
		* vfs.init();
		* // Here you insert the root path where all your resources must be found
		* vfs.setSystemResourcesBasePath(path);
		* // After configure systemResourceBasePath, all resources are inside this directory.
		* // Here you configure a root path where you'll write your deployed files. This directory must be inside the directory you set
		* // in <i>vfs.setSystemResourcesBasePath</i>.
		* vfs.setWriteDirectory(path)
		* <br>
		* <b>[Add resources to be searched for]</b>
		* // add locations where you put your resources in the order in wich you'll search. 
		* // If a file with the same name is into location 2 and 3, then the first one will be choosen. This could be a good mechanism to add mods
		* vfs.addLocationToSearch(files_location_1, 1);
		* vfs.addLocationToSearch(files_location_2, 2);
		* vfs.addLocationToSearch(files_location_3, 3);
		* </code>
		* After that you can check if a file exists, deploy files or load directly into memory. 
		*/
		class CVirtualFileSystem
		{	
		public:
			enum DEPLOY_MODE{
				DPMOD_NORMAL,
				DPMOD_SHADOW,
				DPMOD_SHADOW_WITH_EXTENSION
			};
		private:
			/// where to find zip resources that  belonging to the system
			boost::filesystem::path m_systemResourcesBasePath;
			boost::filesystem::path m_writingAllowedPath;
			/// where to find mod resources
			///std::string m_modResourcesBasePath;
			bool m_isInitialized;
			bool m_isReadOnly;
			z3d::core::cuManager<std::string, std::string> m_deployedManager;

			bool pathCreator( boost::filesystem::path path_to_create );

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void setSystemResourcesBasePath(const char* path)
			///
			/// \brief	Sets a system resources base path. 
			///
			/// \author	Ferran Ferri
			/// \date	16/06/2011
			///
			/// \param [in,out]	path	If non-null, pathname. 
			////////////////////////////////////////////////////////////////////////////////////////////////////

			void setSystemResourcesBasePath(const char* path, bool create = false);
			DEPLOY_MODE m_deployMode;

		public:

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	std::string getSystemResourcesBasePath()
			///
			/// \brief	Gets the system resources base path. 
			///
			/// \author	Ferran Ferri
			/// \date	23/06/2011
			///
			/// \return	The system resources base path. 
			////////////////////////////////////////////////////////////////////////////////////////////////////

			std::string getSystemResourcesBasePath(){return m_systemResourcesBasePath.string();}

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	int init(const char* basePath)
			///
			/// \brief	Initialises this object. 
			///
			/// \author	Ferran Ferri
			/// \date	23/06/2011
			///
			/// \param basePath The base path of all other resources.
			/// \return	. 
			////////////////////////////////////////////////////////////////////////////////////////////////////

			int init(const char* basePath, bool create = false);

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	int addLocationToSearch(const char* location, int order)
			///
			/// \brief	Adds a location to search with order 'order'
			///
			/// \author	Ferran Ferri
			/// \date	23/06/2011
			///
			/// \param [in,out]	location	If non-null, the location you want to insert. 
			/// \param	order				The order in wich locations are explorer, starting by 0. 
			///
			/// \return	ZEL_ERROR_NO_ERROR if not problem found
			////////////////////////////////////////////////////////////////////////////////////////////////////

			int addLocationToSearch(const char* location, unsigned int order);
			int setWriteDirectory(const char* location);
			std::string getWriteDirectory() const;
			bool checkIfFileExists(const char* fileName);
			char* loadFileIntoMemory(const char* fileName);
			std::string deployFile(const char* fileName, DEPLOY_MODE mode);
			std::string deployFile(const char* fileName);
			void deleteFile(const char* fileName);
			void deleteDeployedFiles();

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool isInitialized()
			///
			/// \brief	returns true if the system is initialized
			///
			/// \author	Ferran Ferri
			/// \date	28/11/2011
			///
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool isInitialized() const {return m_isInitialized;}
			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void reset()
			///
			/// \brief	resets the class without destroying it, letting the user to re-init (calling init method)
			///
			/// Calling reset, the user deletes all information about write directory path, resources location and base resource location.
			/// Also, all deployed files names are removed of the manager. <b>Note that no files deployed on the hard disk are deleted</b>, so deployed files
			/// remain untouched into the write directory. To delete deployed files, call the corresponding method.
			///
			/// \author	Ferran Ferri
			/// \date	29/06/2011
			///
			////////////////////////////////////////////////////////////////////////////////////////////////////

			void reset();

			void setDeployPolicy(DEPLOY_MODE mode);
			DEPLOY_MODE getDeployPolicy() const;

			bool createSubPath(const char* subPath);
			CVirtualFileSystem(void);
			~CVirtualFileSystem(void);

		};
	};
};
#endif //_ZELESTE_ZEL_UTILS_VIRTUALFILESYSTEM_H_
